home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / stubedit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-30  |  9.1 KB  |  415 lines

  1. /* This is file STUBEDIT.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <io.h>
  19. #include <fcntl.h>
  20.  
  21. #include "gotypes.h"
  22. #include "stubinfo.h"
  23.  
  24. word32 offset_of_info = 0;
  25. word32 size_of_info = 0;
  26.  
  27. StubInfo stub_info = {
  28.   STUB_INFO_MAGIC
  29. };
  30.  
  31. char *key = stub_info.magic;
  32.  
  33. void find_info(char *filename)
  34. {  
  35.   FILE *f;
  36.   int ch, found = 0;
  37.   int key_p;
  38.   long key_max, key_cnt=0;
  39.   unsigned char header[6];
  40.   unsigned char test_magic[16];
  41.  
  42.   f = fopen(filename, "rb");
  43.   if (f == 0)
  44.   {
  45.     char buf[100];
  46.     sprintf(buf, "Fatal error in stubedit reading %s", filename);
  47.     perror(buf);
  48.     exit(1);
  49.   }
  50.  
  51.   fread(header, 6, 1, f);
  52.   key_max = header[4] + header[5]*256 + 1;
  53.   key_max *= 512;
  54.  
  55.   /* First, look for tag */
  56.   fseek(f, -4L, 2);
  57.   fread(test_magic, 4, 1, f);
  58.   offset_of_info = (test_magic[0])
  59.                  | (test_magic[1] << 8)
  60.                  | (test_magic[2] << 16)
  61.                  | (test_magic[3] << 24);
  62.   if (offset_of_info > 0 && offset_of_info < key_max)
  63.   {
  64.     fseek(f, offset_of_info, 0);
  65.     fread(test_magic, 16, 1, f);
  66.     if (strcmp((char *)test_magic, key) == 0)
  67.       found = 1;
  68.   }
  69.  
  70.   if (!found)
  71.   {
  72.     fseek(f, 0L, 0);
  73.     key_p = 0;
  74.     while ((ch = fgetc(f)) != EOF)
  75.     {
  76.       if (ch == key[key_p])
  77.       {
  78.         key_p++;
  79.         if (key[key_p] == 0)
  80.         {
  81.           fgetc(f); /* the NULL */
  82.           offset_of_info = ftell(f) - 16; /* skip the NULL in the file */
  83.           found = 1;
  84.           break;
  85.         }
  86.       }
  87.       else
  88.         key_p = 0;
  89.       key_cnt++;
  90.       if (key_cnt > key_max)
  91.         break;
  92.     }
  93.   }
  94.   if (!found)
  95.   {
  96.     fprintf(stderr, "Error: I cannot find the stub info structure.  Must be either\n");
  97.     fprintf(stderr, "this is not a stub'd program, or it is older and does not have one.\n");
  98.     exit(1);
  99.   }
  100.  
  101.   fseek(f, offset_of_info + 16L, 0);
  102.   fread(&size_of_info, 1, 4, f);
  103.   stub_info.struct_length = size_of_info;
  104.   if (size_of_info > sizeof(StubInfo))
  105.     size_of_info = sizeof(StubInfo);
  106.   fseek(f, offset_of_info, 0);
  107.   fread(&stub_info, 1, (int)size_of_info, f);
  108.   fclose(f);
  109.   return;
  110. }
  111.  
  112. void store_info(char *filename)
  113. {
  114.   FILE *f;
  115.   f = fopen(filename, "r+b");
  116.   if (f == 0)
  117.   {
  118.     char buf[100];
  119.     sprintf(buf, "Fatal error in stubedit writing %s", filename);
  120.     perror(buf);
  121.     exit(1);
  122.   }
  123.   fseek(f, offset_of_info, 0);
  124.   fwrite(&stub_info, 1, (int)size_of_info, f);
  125.   fclose(f);
  126. }
  127.  
  128. char *pose_question(char *question, char *default_answer)
  129. {
  130.   static char response[200];
  131.   printf("%s ? [%s] ", question, default_answer);
  132.   fflush(stdout);
  133.   gets(response);
  134.   if (response[0] == '\0')
  135.     return 0;
  136.   return response;
  137. }
  138.  
  139. typedef void (*PerFunc)(void *address_of_field, char *buffer);
  140.  
  141. void str_v2s(void *addr, char *buf)
  142. {
  143.   if (*(char *)addr == 0)
  144.     strcpy(buf, "\"\"");
  145.   else
  146.   {
  147.     strncpy(buf, (char *)addr, 14);
  148.     buf[14] = 0;
  149.   }
  150. }
  151.  
  152. void str_s2v(void *addr, char *buf)
  153. {
  154.   if (strcmp(buf, "\"\"") == 0)
  155.     *(char *)addr = 0;
  156.   else
  157.   {
  158.     strncpy((char *)addr, buf, 14);
  159.     ((char *)addr)[14] = 0;
  160.   }
  161. }
  162.  
  163. void bool_v2s(void *addr, char *buf)
  164. {
  165.   if (*(word8 *)addr)
  166.     strcpy(buf, "yes");
  167.   else
  168.     strcpy(buf, "no");
  169. }
  170.  
  171. void bool_s2v(void *addr, char *buf)
  172. {
  173.   switch (buf[0])
  174.   {
  175.     case 'y':
  176.     case 'Y':
  177.     case '1':
  178.     case 't':
  179.     case 'T':
  180.       *(char *)addr = 1;
  181.       break;
  182.     case 'n':
  183.     case 'N':
  184.     case '0':
  185.     case 'f':
  186.     case 'F':
  187.       *(char *)addr = 0;
  188.       break;
  189.   }
  190. }
  191.  
  192. void ver_v2s(void *addr, char *buf)
  193. {
  194.   char *field = (char *)(addr);
  195.   char *rtype = "unknown";
  196.   char *fmt = "%d.%d.%s%d";
  197.   switch (field[1])
  198.   {
  199.     case 'a':
  200.       rtype = "alpha";
  201.       break;
  202.     case 'b':
  203.       rtype = "beta";
  204.       break;
  205.     case 'f':
  206.       fmt = "%d.%d";
  207.       break;
  208.     case 'm':
  209.       rtype = "maint";
  210.       break;
  211.     case 's':
  212.       rtype = "special";
  213.       break;
  214.   }
  215.   sprintf(buf, fmt, field[3], field[2], rtype, field[0]);
  216. }
  217.  
  218. void ver_s2v(void *addr, char *buf)
  219. {
  220.   char *field = (char *)(addr);
  221.   int major = 0;
  222.   int minor = 0;
  223.   char rtype;
  224.   int release = 0;
  225.   char rstr[100];
  226.   rstr[0] = 'f';
  227.   sscanf(buf, "%d.%d.%[^0-9]%d", &major, &minor, &rstr, &release);
  228.   rtype = rstr[0];
  229.   field[3] = major;
  230.   field[2] = minor;
  231.   field[1] = rtype;
  232.   field[0] = release;
  233. }
  234.  
  235. void num_v2s(void *addr, char *buf)
  236. {
  237.   word32 v = *(word32 *)addr;
  238.   sprintf(buf, "%#lx (%ldk)", v, v / 1024L);
  239. }
  240.  
  241. void num_s2v(void *addr, char *buf)
  242. {
  243.   word32 r = 0;
  244.   char s = 0;
  245.   sscanf(buf, "%i%c", &r, &s);
  246.   switch (s)
  247.   {
  248.     case 'k':
  249.     case 'K':
  250.       r *= 1024L;
  251.       break;
  252.     case 'm':
  253.     case 'M':
  254.       r *= 1048576L;
  255.       break;
  256.   }
  257.   *(word32 *)addr = r;
  258. }
  259.  
  260. struct {
  261.   char *short_name;
  262.   char *long_name;
  263.   void *addr_of_field;
  264.   PerFunc val2string;
  265.   PerFunc string2val;
  266. } per_field[] = {
  267.   { "extender",
  268.     "Name of program to run as the extender (max 13 chars)",
  269.     stub_info.go32,
  270.     str_v2s, str_s2v
  271.   },
  272.   { "version",
  273.     "Version of GO32 required to run this program",
  274.     stub_info.required_go32_version,
  275.     ver_v2s, ver_s2v
  276.   },
  277.   {
  278.     "minstack",
  279.     "Minimum amount of stack space (bytes/K/M)",
  280.     (void *)(&stub_info.min_stack),
  281.     num_v2s, num_s2v
  282.   },
  283.   {
  284.     "keepmem",
  285.     "Maximum amount of virtual memory to keep when spawning",
  286.     (void *)(&stub_info.max_keep_on_spawn),
  287.     num_v2s, num_s2v
  288.   },
  289.   {
  290.     "runfile",
  291.     "Base name of file to actually run (max 13 chars, \"\"=self)",
  292.     (void *)(&stub_info.actual_file_to_run),
  293.     str_v2s, str_s2v
  294.   },
  295.   {
  296.     "globbing",
  297.     "Enable command-line wildcard expansion (yes/no)",
  298.     (void *)(&stub_info.enable_globbing),
  299.     bool_v2s, bool_s2v,
  300.   },
  301.   {
  302.     "availmem",
  303.     "Amount of conventional memory to leave (bytes/K/M)",
  304.     (void *)(&stub_info.free_conventional_memory),
  305.     num_v2s, num_s2v
  306.   },
  307. };
  308.  
  309. #define NUM_FIELDS (sizeof(per_field) / sizeof(per_field[0]))
  310.  
  311. #define HFORMAT "%-16s %s\n"
  312.  
  313. void give_help(void)
  314. {
  315.   int i;
  316.   fprintf(stderr, "Usage: stubedit [-v] [-h] filename.exe [field=value . . . ]\n");
  317.   fprintf(stderr, "-h = give help   -v = view info  field=value means set w/o prompt\n");
  318.   fprintf(stderr, HFORMAT, "-field-", "-description-");
  319.  
  320.   for (i=0; i < NUM_FIELDS; i++)
  321.     fprintf(stderr, HFORMAT, per_field[i].short_name, per_field[i].long_name);
  322.   exit(1);
  323. }
  324.  
  325. main(int argc, char **argv)
  326. {
  327.   int view_only = 0;
  328.   int i;
  329.   int need_to_save;
  330.  
  331.   if (argc > 1 && strcmp(argv[1], "-h") == 0)
  332.     give_help();
  333.  
  334.   if (argc > 1 && strcmp(argv[1], "-v") == 0)
  335.   {
  336.     view_only = 1;
  337.     argc--;
  338.     argv++;
  339.   }
  340.  
  341.   if (argc < 2)
  342.     give_help();
  343.  
  344.   find_info(argv[1]);
  345.  
  346.   if (view_only)
  347.   {
  348.     char buf[100];
  349.     fprintf(stderr, HFORMAT, "-value-", "-field description-");
  350.     for (i=0; i<NUM_FIELDS; i++)
  351.     {
  352.       if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
  353.       {
  354.         per_field[i].val2string(per_field[i].addr_of_field, buf);
  355.         fprintf(stderr, HFORMAT, buf, per_field[i].long_name);
  356.       }
  357.     }
  358.     exit(0);
  359.   }
  360.  
  361.   if (argc > 2)
  362.   {
  363.     int f, got, got_any = 0;
  364.     char fname[100], fval[100];
  365.     for (i=2; i < argc; i++)
  366.     {
  367.       fname[0] = 0;
  368.       fval[0] = 0;
  369.       sscanf(argv[i], "%[^=]=%s", fname, fval);
  370.       got = 0;
  371.       for (f=0; f<NUM_FIELDS; f++)
  372.       {
  373.         if (strcmp(per_field[f].short_name, fname) == 0)
  374.         {
  375.           got = 1;
  376.           got_any = 1;
  377.           if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
  378.           {
  379.             per_field[f].string2val(per_field[f].addr_of_field, fval);
  380.           }
  381.           else
  382.             fprintf(stderr, "Warning: This stub does not support field %s\n", fname);
  383.         }
  384.       }
  385.       if (!got)
  386.       {
  387.         fprintf(stderr, "Error: %s is not a valid field name.\n", fname);
  388.         give_help();
  389.       }
  390.     }
  391.     if (got_any)
  392.       store_info(argv[1]);
  393.     return 0;
  394.   }
  395.  
  396.   need_to_save = 0;
  397.   for (i=0; i<NUM_FIELDS; i++)
  398.   {
  399.     char buf[100], *resp;
  400.     if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
  401.     {
  402.       per_field[i].val2string(per_field[i].addr_of_field, buf);
  403.       if ((resp = pose_question(per_field[i].long_name, buf)) != 0)
  404.       {
  405.         per_field[i].string2val(per_field[i].addr_of_field, resp);
  406.         need_to_save = 1;
  407.       }
  408.     }
  409.   }
  410.   if (need_to_save)
  411.     store_info(argv[1]);
  412.  
  413.   return 0;
  414. }
  415.